﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Medianamik.Core;
using System.Globalization;
using System.Text.RegularExpressions;
using Medianamik.Core.Urls;
using Medianamik.Core.Configuration;
using System.Configuration;

namespace Medianamik.Core.Urls
{
    public class PathBuilder : IPathBuilder
    {
        private IUrlDictionary _urlDico;
        private IPathSegmentFormater _segmentFormater;
        public PathBuilder(IUrlDictionary pUrlDico, IPathSegmentFormater pSegmentFormater )
        {
            _urlDico = pUrlDico;
            _segmentFormater = pSegmentFormater;
        }
        
        /// <summary>
        /// Contruit un Url avec les segments passés en paramètre.
        /// Le préfixe et l'extension servent à la vérification de l'existance
        /// d'un path similaire dans le UrlDictionary mais ils ne sont pas 
        /// ajoutés au path final.
        /// </summary>
        /// <param name="pSegments"></param>
        /// <param name="pCulture"></param>
        /// <param name="pPrefix"></param>
        /// <param name="pDefaultExtension"></param>
        /// <returns></returns>
        public string BuildUrl(PathSegmentCollection pSegments, CultureInfo pCulture, string pPrefix, string pDefaultExtension)
        {
            var relativeUrlWithoutExtension = BuildRelativeUrlWithoutExtension(pSegments);

            if (IsUnic(relativeUrlWithoutExtension))

            return EnsureUnicity(generatedPath, pCulture, pPrefix, pDefaultExtension);
        }

        private string BuildRelativeUrlWithoutExtension(PathSegmentCollection pSegments)
        {
            StringBuilder urlBuilder = new StringBuilder();
            pSegments.ToList().ForEach(s =>
                                           {
                                               urlBuilder.Append("/" + _segmentFormater.Format(s.Value));
                                           });
            return urlBuilder.ToString();
        }

        private string EnsureUnicity(string path, CultureInfo pCulture, string pPrefix, string pDefaultExtension)
        {
            //cette variable nous sert à regarder dans le UrlDictionary si l'url existe déjà
            var realPath = GetRealPath(pPrefix, path, pDefaultExtension);

            var similarPaths = _urlDico.GetSimilarPaths(realPath);

            if (similarPaths.Length > 0)
            {
                var isNewCulture = similarPaths.All(p => !string.Equals(p.Culture.Name, pCulture.Name));
                if (isNewCulture)
                {
                    //Les autre pages existent dans d'autres cultures
                    //On regarde si on peut ajouter le CultureName au nom de la page
                    var revisedPath = path + "-" + pCulture.Name.ToLowerInvariant();
                    var revisedRealPath = realPath + "-" + pCulture.Name.ToLowerInvariant();
                    
                    if (!_urlDico.ContainsUrl(revisedRealPath))
                    {
                        //Quelle chance !
                        return revisedPath;
                    }
                }

                //Ajouter une chaine aléatoire avant l'extension
                path = path + "-" + Guid.NewGuid().ToString("N").Substring(0, 6);
            }

            return path;
        }

        public string GetRealPath(string prefix,string path, string pDefaultExtension)
        {
            var properPrefix = FormatPrefixProper(prefix);
            return properPrefix + '/' + path.TrimStart('/') + (path.EndsWith("/") || path.Contains('.') ? string.Empty : pDefaultExtension);
        }

        private string FormatPrefixProper(string pPrefix)
        {
            return string.IsNullOrEmpty(pPrefix)
                       ? string.Empty
                       : '/' + pPrefix.TrimStart('/').TrimEnd('/');
        }

        public bool UrlIsUnique(string realPath)
        {
            return _urlDico.GetSimilarPaths(realPath).Count() < 1;
        }

        public bool UrlIsValid(string realPath)
        {
            return Regex.IsMatch(realPath, "^(/[0-9a-zA-Z_]+)+((/[0-9a-zA-Z_]+)*|(-[0-9a-zA-Z_]+)*)*(\\.[a-zA-Z]+)?$");
            //Doit commencer par un /
            //Ne doit pas contenir de répétitions de -
            //Peut avoir une extension .html, .apsx, etc.
            //Voir Maxime si modification
        }

        
    }
}
